#include "libPPD.h"

/* Manejo ListasPRAID */

t_listaPRAID *crearListaPRAID()
{
	t_listaPRAID *lista = (t_listaPRAID *)malloc( sizeof(t_listaPRAID) );
	lista->head = NULL;
	return lista;
}

/*Saca el primer nodo de la lista, si no hay nada retorna -1 */
void sacarDeLaListaPRAID (t_nodoPRAID ** nodoAux)
{
	extern t_listaPRAID *listaPedidosPRAID;
	extern pthread_mutex_t bloqueaLista;
	extern sem_t listaPedidosVacia;
	extern t_config config;
	int32_t bloquearLista = 0;
	static int32_t cantPedidosAtendidos = 0;

	cantPedidosAtendidos ++;

	bloquearLista = pthread_mutex_lock(&bloqueaLista);

	if( listaPedidosPRAID->head == NULL)
		perror("No hay elementos en la lista\n");
	*nodoAux = listaPedidosPRAID->head;
	listaPedidosPRAID->head = listaPedidosPRAID->head->next;

	bloquearLista = pthread_mutex_unlock(&bloqueaLista);

	if ((strcmp(config.algoritmo, "NSTEPSCAN") == 0) && (listaPedidosPRAID->head == NULL) && (config.cantPedidos == cantPedidosAtendidos))
	{
		cantPedidosAtendidos = 0;
		sem_post (&listaPedidosVacia);
	}
}

/*Agrega en la posicion dada el nuevo nodo */
void agregarEnLaListaPRAID(int32_t posicion, t_NIPC paqueteNuevo)
{
	extern  t_listaPRAID *listaPedidosPRAID;
	extern t_log *loguear;
	int32_t cont;
	t_nodoPRAID* nodo = NULL;

	t_nodoPRAID *nuevoNodo;
	nuevoNodo = (t_nodoPRAID *) calloc (1, sizeof(t_nodoPRAID));
	NIPC_crearpaquete(paqueteNuevo.DescriptorID, paqueteNuevo.PayloadDescriptor, paqueteNuevo.PayloadLength, paqueteNuevo.payload, paqueteNuevo.nroSector, &nuevoNodo->paquete);

	if( posicion == 0)
	{
		nuevoNodo->next = listaPedidosPRAID->head;
		listaPedidosPRAID->head = nuevoNodo;
	}
	else if (posicion > 0)
	{
		nodo = listaPedidosPRAID->head;
		for(cont=0 ; cont < (posicion-1) && nodo != NULL; nodo=nodo->next,cont++);
		if (nodo == NULL)
		{
			nuevoNodo->next = NULL;
			nodo = nuevoNodo;
		}
		else
		{
			nuevoNodo->next =  nodo->next;
			nodo->next = nuevoNodo;
		}
	}
	else
	{
		log_error (loguear, "PPD", "Message error: %s", "Posicion negativa, no se puede agregar a la lista");
	}

}



/* Manejo de ListasPFS */
t_listaPFS *crearListaPFS()
{
	t_listaPFS *lista = (t_listaPFS *)malloc( sizeof(t_listaPFS) );
	lista->head = NULL;
	return lista;
}

void sacarDeLaListaPFS (t_nodoPFS **nodoAux)
{
	extern t_listaPFS *listaPedidosPFS;
	extern pthread_mutex_t bloqueaLista;
	extern sem_t listaPedidosVacia;
	extern t_config config;
	static int32_t cantPedidosAtendidos = 0;
	int32_t bloquearLista = 0;

	cantPedidosAtendidos ++;
	bloquearLista = pthread_mutex_lock(&bloqueaLista);

	if( listaPedidosPFS->head == NULL)
		perror("No hay elementos en la lista\n");
	*nodoAux = listaPedidosPFS->head;
	listaPedidosPFS->head = listaPedidosPFS->head->next;

	bloquearLista = pthread_mutex_unlock(&bloqueaLista);

	if ((strcmp(config.algoritmo, "NSTEPSCAN") == 0) && (listaPedidosPFS->head == NULL) && (config.cantPedidos == cantPedidosAtendidos))
	{
		cantPedidosAtendidos = 0;
		sem_post (&listaPedidosVacia);
	}

}

void agregarEnLaListaPFS (int32_t posicion, t_NIPC paquete, int32_t socketFD)
{
	extern  t_listaPFS *listaPedidosPFS;
	extern pthread_mutex_t bloqueaLista;
	extern t_log *loguear;
	int32_t cont;
	t_nodoPFS* nodo = NULL;

	t_nodoPFS *nuevoNodo;
	nuevoNodo = (t_nodoPFS *) calloc (1, sizeof(t_nodoPFS));
	NIPC_crearpaquete (paquete.DescriptorID, paquete.PayloadDescriptor, paquete.PayloadLength, paquete.payload, paquete.nroSector, &nuevoNodo->paquete);
	nuevoNodo->socket = socketFD;


	if( posicion == 0)
	{
		nuevoNodo->next = listaPedidosPFS->head;
		listaPedidosPFS->head = nuevoNodo;
	}
	else if (posicion > 0)
	{
		nodo = listaPedidosPFS->head;
		for(cont=0; cont < (posicion-1) && nodo != NULL; nodo=nodo->next, cont++);

		if (nodo == NULL)
		{
			nuevoNodo->next = NULL;
			nodo = nuevoNodo;
		}
		else
		{
			nuevoNodo->next =  nodo->next;
			nodo->next = nuevoNodo;
		}
	}
	else
	{
		log_error (loguear, "PPD", "Message error: %s", "Posicion negativa, no se puede agregar a la lista");
	}

}
